package com.wlyuan.index.application.listener;

import com.wlyuan.core.domain.event.DomainEventListener;
import com.wlyuan.core.domain.valueobj.CombineId;
import com.wlyuan.core.domain.valueobj.QuotationId;
import com.wlyuan.core.domain.valueobj.WaybillId;
import com.wlyuan.index.api.dto.combine.CombineIndexDTO;
import com.wlyuan.index.domain.index.event.CombineQuoteUpdated;
import com.wlyuan.index.domain.index.service.WaybillIndexRenewService;
import com.wlyuan.index.domain.source.Source;
import com.wlyuan.index.domain.source.repository.SourceRepository;
import com.wlyuan.index.domain.source.valueobj.SourceId;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author yuanjie
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CombineQuoteUpdatedEventListener implements DomainEventListener<CombineQuoteUpdated> {
    private final SourceRepository sourceRepository;
    private final WaybillIndexRenewService renewService;

    /**
     * 合单报价绑定到运单上
     */
    private void addBounds(List<WaybillId> waybillIds, QuotationId quotationId) {
        var boundId = new SourceId(quotationId);
        var sourceIds = waybillIds
                .parallelStream()
                .map(SourceId::new)
                .collect(Collectors.toList());
        sourceRepository.bound(sourceIds, boundId);
    }

    private Source getCombineSource(CombineQuoteUpdated event) {
        CombineId combineId = event.getBusinessId();
        return sourceRepository.ofId(new SourceId(combineId));
    }

    @Subscribe(threadMode = ThreadMode.ASYNC)
    @Override
    public void handle(CombineQuoteUpdated event) {
        assert null != event.getQuotation();
        var source = this.getCombineSource(event);
        if (null == source) {
            logger.error("合单数据不存在: {}", event);
            return;
        }

        CombineIndexDTO combine = source.decode();
        if (null == combine) {
            logger.error("合单数据不正确: {}", event);
            return;
        }

        if (CollectionUtils.isEmpty(combine.getWaybills())) {
            logger.warn("合单运单列表为空: {}", event);
            return;
        }

        var waybillIds = combine.getWaybills()
                .stream()
                .map(waybill -> new WaybillId(waybill.getWaybillId()))
                .collect(Collectors.toList());
        // 关联合单报价到每个运单
        this.addBounds(waybillIds, event.getQuotationId());

        // 重建运单索引
        renewService.addAll(waybillIds);
    }
}
